package com.hula.util;

import com.alibaba.fastjson.JSONObject;
import com.hula.init.InitHttpConnection;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;

/**
 * @author liuhe
 * @date 2021/3/25
 * @Description Http请求工具
 */
@Slf4j
public class HttpClientUtil {

    /**
     * https Get请求
     */
    public static String doHttpsGet(String url, Map<String, Object> params) {
        return doHttpsGet(url, params, null);
    }

    /**
     * https Get请求
     */
    public static String doHttpsGet(String url, Map<String, Object> params, Map<String, String> headers) {
        String result = "";
        HttpResponse response = null;
        try {
            // 获取httpGet请求
            HttpGet httpGet = buildGetRequest(url, params, headers);
            response = doHttpsAction(httpGet);
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                log.error("请求失败：>>>{}", response);
            }
            result = EntityUtils.toString(response.getEntity());
            log.info("返回数据：>>>{}", result);
        } catch (Exception e) {
            log.error("请求失败:{}", e.getStackTrace());
        } finally {
            if (response != null) {
                try {
                    EntityUtils.consume(response.getEntity());
                } catch (IOException e) {
                    log.error("关闭资源失败：{}", e.getMessage());
                }
            }
        }
        return result;
    }

    /**
     * https Post请求
     */
    public static String doHttpsPostJson(String url, Map<String,Object> params) {
        return doHttpsPostJson(url, params, null);
    }

    /**
     * https Post请求
     */
    public static String doHttpsPostJson(String url, Map<String,Object> params, Map<String,String> header) {
        String result = "";
        // 创建httpclient对象
        HttpClient httpClient = InitHttpConnection.getHttpClient();
        HttpResponse response = null;
        try {
            HttpPost httpPost = buildPostRequest(url, params, header);
            response = httpClient.execute(httpPost);
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                log.error("请求失败：>>>{}", response);
            }
            result = EntityUtils.toString(response.getEntity());
            log.info("返回数据：>>>{}", result);
        } catch (Exception e) {
            log.error("请求失败:{}", e.getStackTrace());
        }finally {
            if (response != null) {
                try {
                    EntityUtils.consume(response.getEntity());
                } catch (IOException e) {
                    log.error("关闭资源失败：{}" + e.getMessage());
                }
            }
        }
        return result;
    }

    /**
     * 添加默认头信息（json格式)
     * @param httpPost
     */
    private static void addDefaultHeader(HttpPost httpPost) {
        httpPost.addHeader("Content-Type", "application/json; charset=utf-8");
    }

    /**
     * 获取http Post请求
     * @param url 请求地址
     * @param params 请求参数
     * @param header 请求header
     * @return 返回请求对象
     */
    private static HttpPost buildPostRequest(String url, Map<String, Object> params, Map<String, String> header) {
        HttpPost httpPost = new HttpPost(url);
        // 参数键值对
        addDefaultHeader(httpPost);
        final String paramStr = JSONObject.toJSONString(params);
        log.info("POST请求参数:{},请求路径:{}", paramStr, url);
        if (params != null && !params.isEmpty()) {
            httpPost.setEntity(new StringEntity(paramStr, "UTF-8"));
        }
        // header信息
        if(null != header && !header.isEmpty()){
            for (Map.Entry<String,String> entry:header.entrySet()){
                httpPost.addHeader(entry.getKey(),entry.getValue());
            }
        }
        return httpPost;
    }

    /**
     * 获取http Get请求
     * @param url 请求地址
     * @param params 请求参数
     * @param headers 请求header
     * @return 返回请求对象
     */
    private static HttpGet buildGetRequest(String url, Map<String, Object> params, Map<String, String> headers) throws URISyntaxException {
        URIBuilder uriBuilder = new URIBuilder(url);
        if (null != params && !params.isEmpty()) {
            for (Map.Entry<String, Object> entry : params.entrySet()) {
                uriBuilder.addParameter(entry.getKey(), String.valueOf(entry.getValue()));
            }
        }
        URI uri = uriBuilder.build();
        log.info("Get请求参数:{},请求路径:{}", params, url);
        // 创建get请求
        HttpGet httpGet = new HttpGet(uri);
        // 添加header
        if(null != headers && !headers.isEmpty()){
            for(Map.Entry<String, String> header : headers.entrySet()){
                httpGet.setHeader(header.getKey(), header.getValue());
            }
        }
        return httpGet;
    }

    /**
     * 执行https请求
     * @param request https请求
     * @return https响应
     */
    private static HttpResponse doHttpsAction(HttpUriRequest request) throws IOException {
        return doHttpsAction(request, false, 1);
    }

    /**
     * 执行https请求
     * @param request https请求
     * @param autoRetry 重试
     * @param maxRetryNumber 最大重试数
     * @return https响应
     * @throws IOException
     */
    private static HttpResponse doHttpsAction(HttpUriRequest request,boolean autoRetry, int maxRetryNumber) throws IOException {
        HttpClient httpClient = InitHttpConnection.getHttpClient();
        HttpResponse response = httpClient.execute(request);
        int retryTimes = 0;
        while (HttpStatus.SC_INTERNAL_SERVER_ERROR <= response.getStatusLine().getStatusCode()
                && autoRetry && retryTimes < maxRetryNumber) {
            response = httpClient.execute(request);
            retryTimes ++;
            log.info("Get请求重试第{}次", retryTimes);
        }
        return response;
    }
}
